package com.wuage.application.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wuage.application.IUacDictionaryService;
import com.wuage.application.IUacTenantService;
import com.wuage.domain.mapper.UacDictionaryMapper;
import com.wuage.domain.model.UacDictionary;
import com.wuage.domain.model.UacTenant;
import com.wuage.infrastructure.security.LoginUser;
import com.wuage.infrastructure.utils.BeanUtils;
import com.wuage.infrastructure.utils.JwtUtils;
import com.wuage.interfaces.account.domain.DictionaryPageDO;
import com.wuage.interfaces.dictionary.domain.UacDictionaryDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.LongStream;

/**
 * @author Shynin
 * @version 1.0
 * @date 2020-09-21 16:16
 */
@Slf4j
@Service
public class UacDictionaryServiceImpl extends ServiceImpl<UacDictionaryMapper, UacDictionary> implements IUacDictionaryService {
    @Resource
    private UacDictionaryMapper sysDictionaryMapper;
    @Resource
    private IUacTenantService uacTenantService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean create(String type, String target) {
        UacDictionary sysDictionary =
                UacDictionary.builder()
                        .classification(type)
                        .target(target)
                        .accountId(JwtUtils.getLoginUser().getId())
                        .build();
        return sysDictionaryMapper.insert(sysDictionary) > 0;
    }

    @Override
    public List<UacDictionary> getAllByAccount(Integer type, Boolean isSystem) {
        QueryWrapper<UacDictionary> queryWrapper = new QueryWrapper<>();
        if (!isSystem) {
            queryWrapper.eq("account_id", JwtUtils.getLoginUser().getId());
        }
        queryWrapper.eq("classification", type);
        return sysDictionaryMapper.selectList(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteByAccount(Long id) {
        UpdateWrapper<UacDictionary> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("account_id", JwtUtils.getLoginUser().getId());
        updateWrapper.eq("id", id);
        return sysDictionaryMapper.delete(updateWrapper) > 0;
    }

    @Override
    public UacDictionary getById(Long id) {
        return sysDictionaryMapper.selectById(id);
    }


    @Override
    public Page<UacDictionary> getByClassification(DictionaryPageDO pageDO, Long tenantId) {
        return sysDictionaryMapper.selectPage(new Page<>(pageDO.getCurrent(), pageDO.getSize())
                , new QueryWrapper<UacDictionary>().lambda().eq(UacDictionary::getClassification, pageDO.getClassification())
                        .eq(Objects.nonNull(pageDO.getParentId()), UacDictionary::getParentId, pageDO.getParentId())
                        .eq(UacDictionary::getTenantId, tenantId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        Long tenantId = JwtUtils.getLoginUser().getTenantId();
        int i = sysDictionaryMapper.delete(this.lambdaQuery().eq(UacDictionary::getTenantId, tenantId));
        if (i < 1) {
            return false;
        }
        recursionDeleteByIds(Collections.singletonList(id), tenantId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addDictionary(UacDictionaryDO uacDictionaryDO) {
        Long tenantId = JwtUtils.getLoginUser().getTenantId();
        UacDictionary uacDictionary = BeanUtils.copyProperties(uacDictionaryDO, UacDictionary.class);
        UacTenant tenant = uacTenantService.getById(tenantId);
        uacDictionary.setTenantId(tenantId);
        uacDictionary.setTenantName(Objects.isNull(tenant) ? null : tenant.getName());
        return this.save(uacDictionary);
    }

    /**
     * 递归删除字典
     *
     * @param ids 父节点Id集合
     */
    private void recursionDeleteByIds(List<Long> ids, Long tenantId) {
        List<UacDictionary> uacDictionaries = sysDictionaryMapper.selectList(this.lambdaQuery().in(UacDictionary::getParentId, ids).eq(UacDictionary::getTenantId, tenantId));
        if (CollectionUtils.isEmpty(uacDictionaries)) {
            return;
        }
        List<Long> collect = uacDictionaries.stream().map(UacDictionary::getId).collect(Collectors.toList());
        sysDictionaryMapper.deleteBatchIds(collect);
        recursionDeleteByIds(collect, tenantId);
    }
}
